﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Terra.Core.Common.Enums.Identity;
using Terra.Core.Common.ErrorCodes.Constants;
using Terra.Core.Common.Exceptions;
using Terra.Core.Common.Models.Pagination;
using Terra.Core.Common.Utils;
using Terra.Data.Entities.Identity;
using Terra.Data.Models.Identity;
using Terra.Data.Repository.Identity;
using Terra.Data.UnitOfWork;
using Terra.Service.Common.Base;
using Terra.Service.Identity.Interfaces;

namespace Terra.Service.Identity.Implementations
{
    /// <summary>
    /// 用户服务实现
    /// </summary>
    public class UserService : AppServiceBase, IUserService
    {
        private readonly IUserRepository _userRepository;
        private readonly IRoleRepository _roleRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="unitOfWork">工作单元</param>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="roleRepository">角色仓储</param>
        /// <param name="mapper">对象映射器</param>
        public UserService(
            IUnitOfWork unitOfWork,
            IUserRepository userRepository,
            IRoleRepository roleRepository,
            IMapper mapper) : base(unitOfWork, mapper)
        {
            _userRepository = userRepository ?? throw new ArgumentNullException(nameof(userRepository));
            _roleRepository = roleRepository ?? throw new ArgumentNullException(nameof(roleRepository));
        }

        /// <summary>
        /// 获取用户
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns>用户实体</returns>
        public async Task<User> GetUserAsync(Guid userId)
        {
            var user = await _userRepository.GetByIdAsync(userId);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {userId} 的用户");
            }
            return user;
        }

        /// <summary>
        /// 分页查询用户
        /// </summary>
        /// <param name="query">查询条件</param>
        /// <returns>分页结果</returns>
        public async Task<PagedList<UserItemDto>> GetPagedUsersAsync(UserQueryDto query)
        {
            // 获取分页数据
            var pagedUsers = await _userRepository.GetPagedListAsync(query);

            // 转换为DTO
            var userItems = pagedUsers.Items.Select(async user =>
            {
                var dto = Mapper.Map<UserItemDto>(user);

                // 获取用户角色
                var roleNames = await _userRepository.GetUserRoleNamesAsync(user.Id);
                dto.Roles = roleNames;
                dto.RoleIds =  await _userRepository.GetUserRoleIdsAsync(user.Id);

                return dto;
            }).Select(t => t.Result).ToList();

            // 创建分页结果
            return new PagedList<UserItemDto>(
                userItems,
                pagedUsers.TotalCount,
                pagedUsers.PageIndex,
                pagedUsers.PageSize);
        }

        /// <summary>
        /// 获取用户详情
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>用户详情</returns>
        public async Task<UserDetailDto> GetUserDetailAsync(Guid id)
        {
            // 获取用户信息，包含角色
            var user = await _userRepository.GetUserDetailAsync(id, true);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {id} 的用户");
            }

            // 转换为DTO
            var dto = Mapper.Map<UserDetailDto>(user);

            // 获取角色信息
            var roleIds = await _userRepository.GetUserRoleIdsAsync(id);
            var roleNames = await _userRepository.GetUserRoleNamesAsync(id);

            dto.RoleIds = roleIds;
            dto.Roles = roleNames;

            return dto;
        }

        /// <summary>
        /// 创建用户
        /// </summary>
        /// <param name="dto">创建参数</param>
        /// <returns>创建的用户ID</returns>
        public async Task<Guid> CreateUserAsync(UserCreateDto dto)
        {
            // 验证用户名唯一性
            if (await _userRepository.IsUserNameExistsAsync(dto.UserName))
            {
                throw new BusinessException(SecurityErrorCodes.USER_NAME_ALREADY_EXISTS, "用户名已存在");
            }

            // 验证邮箱唯一性
            if (!string.IsNullOrWhiteSpace(dto.Email) && await _userRepository.IsEmailExistsAsync(dto.Email))
            {
                throw new BusinessException(SecurityErrorCodes.USER_EMAIL_ALREADY_EXISTS, "邮箱已存在");
            }

            // 验证手机号唯一性
            if (!string.IsNullOrWhiteSpace(dto.PhoneNumber) && await _userRepository.IsPhoneNumberExistsAsync(dto.PhoneNumber))
            {
                throw new BusinessException(SecurityErrorCodes.USER_PHONE_ALREADY_EXISTS, "手机号已存在");
            }

            // 验证密码复杂度
            if (!IsPasswordValid(dto.Password))
            {
                throw new BusinessException(SecurityErrorCodes.USER_PASSWORD_INVALID, "密码不符合复杂度要求");
            }

            // 创建用户实体
            var user = Mapper.Map<User>(dto);

            // 规范化用户名和邮箱
            user.NormalizedUserName = user.UserName.ToUpperInvariant();
            user.NormalizedEmail = user.Email?.ToUpperInvariant();

            // 设置初始值
            user.SecurityStamp = Guid.NewGuid().ToString();
            user.Id = Guid.NewGuid();
            user.CreatedTime = DateTime.UtcNow;
            user.LastPasswordChangedTime = DateTime.UtcNow;

            // 创建用户
            var createdUser = await _userRepository.CreateAsync(user, dto.Password);

            // 如果有角色ID列表，分配角色
            if (dto.RoleIds != null && dto.RoleIds.Count > 0)
            {
                // 检查角色是否存在
                foreach (var roleId in dto.RoleIds)
                {
                    var role = await _roleRepository.GetByIdAsync(roleId);
                    if (role == null)
                    {
                        throw new NotFoundException($"未找到ID为 {roleId} 的角色");
                    }
                }

                await _userRepository.AssignRolesToUserAsync(createdUser.Id, dto.RoleIds);
            }

            return createdUser.Id;
        }

        /// <summary>
        /// 更新用户
        /// </summary>
        /// <param name="dto">更新参数</param>
        /// <returns>更新结果</returns>
        public async Task<bool> UpdateUserAsync(UserUpdateDto dto)
        {
            // 获取用户
            var user = await _userRepository.GetByIdAsync(dto.Id);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {dto.Id} 的用户");
            }

            // 系统用户不允许修改
            if (user.UserType == UserType.System)
            {
                throw new BusinessException(SecurityErrorCodes.SYSTEM_USER_MODIFY_FORBIDDEN, "系统用户不允许修改");
            }

            // 验证邮箱唯一性
            if (!string.IsNullOrWhiteSpace(dto.Email) &&
                dto.Email != user.Email &&
                await _userRepository.IsEmailExistsAsync(dto.Email, dto.Id))
            {
                throw new BusinessException(SecurityErrorCodes.USER_EMAIL_ALREADY_EXISTS, "邮箱已存在");
            }

            // 验证手机号唯一性
            if (!string.IsNullOrWhiteSpace(dto.PhoneNumber) &&
                dto.PhoneNumber != user.PhoneNumber &&
                await _userRepository.IsPhoneNumberExistsAsync(dto.PhoneNumber, dto.Id))
            {
                throw new BusinessException(SecurityErrorCodes.USER_PHONE_ALREADY_EXISTS, "手机号已存在");
            }

            // 更新用户基本信息
            Mapper.Map(dto, user);

            // 规范化邮箱
            user.NormalizedEmail = user.Email?.ToUpperInvariant();

            // 更新用户信息
            await _userRepository.UpdateAsync(user);

            // 如果有角色ID列表，更新角色分配
            if (dto.RoleIds != null)
            {
                // 检查角色是否存在
                foreach (var roleId in dto.RoleIds)
                {
                    var role = await _roleRepository.GetByIdAsync(roleId);
                    if (role == null)
                    {
                        throw new NotFoundException($"未找到ID为 {roleId} 的角色");
                    }
                }

                // 更新角色分配
                await _userRepository.AssignRolesToUserAsync(user.Id, dto.RoleIds);
            }

            return true;
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="id">用户ID</param>
        /// <returns>删除结果</returns>
        public async Task<bool> DeleteUserAsync(Guid id)
        {
            // 检查用户是否存在
            var user = await _userRepository.GetByIdAsync(id);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {id} 的用户");
            }

            // 系统用户不允许删除
            if (user.UserType == UserType.System)
            {
                throw new BusinessException(SecurityErrorCodes.SYSTEM_USER_MODIFY_FORBIDDEN, "系统用户不允许删除");
            }

            // 执行删除
            await _userRepository.DeleteAsync(user);
            return true;
        }

        /// <summary>
        /// 批量删除用户
        /// </summary>
        /// <param name="ids">用户ID列表</param>
        /// <returns>删除数量</returns>
        public async Task<int> BatchDeleteUsersAsync(List<Guid> ids)
        {
            if (ids == null || ids.Count == 0)
            {
                return 0;
            }

            // 获取用户列表
            var users = await _userRepository.GetListAsync(u => ids.Contains(u.Id));

            // 过滤掉系统用户
            var eligibleUsers = users.Where(u => u.UserType != UserType.System).ToList();

            if (eligibleUsers.Count == 0)
            {
                return 0;
            }

            // 执行批量删除
            foreach (var user in eligibleUsers)
            {
                user.IsDeleted = true;
                user.DeletedTime = DateTime.UtcNow;
                await _userRepository.UpdateAsync(user);
            }

            return eligibleUsers.Count;
        }

        /// <summary>
        /// 更改密码
        /// </summary>
        /// <param name="dto">更改密码参数</param>
        /// <returns>更改结果</returns>
        public async Task<bool> ChangePasswordAsync(ChangePasswordDto dto)
        {
            // 检查用户是否存在
            var user = await _userRepository.GetByIdAsync(dto.UserId);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {dto.UserId} 的用户");
            }

            // 验证密码复杂度
            if (!IsPasswordValid(dto.NewPassword))
            {
                throw new BusinessException(SecurityErrorCodes.USER_PASSWORD_INVALID, "密码不符合复杂度要求");
            }

            // 验证当前密码
            if (!_userRepository.ValidatePassword(user, dto.CurrentPassword))
            {
                throw new BusinessException(SecurityErrorCodes.InvalidCredentials, "当前密码不正确");
            }

            // 修改密码
            var salt = SecurityUtils.GenerateSalt();
            var hash = SecurityUtils.HashPassword(dto.NewPassword, salt, 10000);

            user.PasswordHash = hash;
            user.PasswordSalt = salt;
            user.SecurityStamp = Guid.NewGuid().ToString();
            user.LastPasswordChangedTime = DateTime.UtcNow;
            user.RequiresPasswordReset = false;

            await _userRepository.UpdateAsync(user);
            return true;
        }

        /// <summary>
        /// 重置密码
        /// </summary>
        /// <param name="dto">重置密码参数</param>
        /// <returns>重置结果</returns>
        public async Task<bool> ResetPasswordAsync(ResetPasswordDto dto)
        {
            // 检查用户是否存在
            var user = await _userRepository.GetByIdAsync(dto.UserId);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {dto.UserId} 的用户");
            }

            // 验证密码复杂度
            if (!IsPasswordValid(dto.NewPassword))
            {
                throw new BusinessException(SecurityErrorCodes.USER_PASSWORD_INVALID, "密码不符合复杂度要求");
            }

            // 重置密码
            var salt = SecurityUtils.GenerateSalt();
            var hash = SecurityUtils.HashPassword(dto.NewPassword, salt, 10000);

            user.PasswordHash = hash;
            user.PasswordSalt = salt;
            user.SecurityStamp = Guid.NewGuid().ToString();
            user.LastPasswordChangedTime = DateTime.UtcNow;
            user.RequiresPasswordReset = false;

            await _userRepository.UpdateAsync(user);
            return true;
        }

        /// <summary>
        /// 更新用户状态
        /// </summary>
        /// <param name="dto">状态更新参数</param>
        /// <returns>更新结果</returns>
        public async Task<bool> UpdateUserStatusAsync(UserStatusUpdateDto dto)
        {
            // 检查用户是否存在
            var user = await _userRepository.GetByIdAsync(dto.UserId);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {dto.UserId} 的用户");
            }

            // 系统用户不允许修改状态
            if (user.UserType == UserType.System)
            {
                throw new BusinessException(SecurityErrorCodes.SYSTEM_USER_MODIFY_FORBIDDEN, "系统用户不允许修改状态");
            }

            try
            {
                // 更新状态
                user.Status = dto.Status;
                user.LastModifiedTime = DateTime.UtcNow;
                await _userRepository.UpdateAsync(user);
                return true;
            }
            catch (Exception)
            {
                throw new BusinessException(SecurityErrorCodes.USER_STATUS_UPDATE_FAILED, "用户状态更新失败");
            }
        }

        /// <summary>
        /// 为用户分配角色
        /// </summary>
        /// <param name="dto">角色分配参数</param>
        /// <returns>操作结果</returns>
        public async Task<bool> AssignRolesToUserAsync(UserRoleAssignDto dto)
        {
            // 检查用户是否存在
            var user = await _userRepository.GetByIdAsync(dto.UserId);
            if (user == null)
            {
                throw new NotFoundException($"未找到ID为 {dto.UserId} 的用户");
            }

            // 系统用户不允许修改角色
            if (user.UserType == UserType.System)
            {
                throw new BusinessException(SecurityErrorCodes.SYSTEM_USER_MODIFY_FORBIDDEN, "系统用户不允许修改角色");
            }

            // 检查角色是否存在
            if (dto.RoleIds != null && dto.RoleIds.Count > 0)
            {
                foreach (var roleId in dto.RoleIds)
                {
                    var role = await _roleRepository.GetByIdAsync(roleId);
                    if (role == null)
                    {
                        throw new NotFoundException($"未找到ID为 {roleId} 的角色");
                    }
                }
            }

            try
            {
                // 分配角色
                await _userRepository.AssignRolesToUserAsync(dto.UserId, dto.RoleIds);
                return true;
            }
            catch (Exception)
            {
                throw new BusinessException(SecurityErrorCodes.USER_ROLE_ASSIGN_FAILED, "角色分配失败");
            }
        }

        /// <summary>
        /// 检查用户名是否存在
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="excludeUserId">排除的用户ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> IsUserNameExistsAsync(string userName, Guid? excludeUserId = null)
        {
            return await _userRepository.IsUserNameExistsAsync(userName, excludeUserId);
        }

        /// <summary>
        /// 检查邮箱是否存在
        /// </summary>
        /// <param name="email">邮箱</param>
        /// <param name="excludeUserId">排除的用户ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> IsEmailExistsAsync(string email, Guid? excludeUserId = null)
        {
            return await _userRepository.IsEmailExistsAsync(email, excludeUserId);
        }

        /// <summary>
        /// 检查手机号是否存在
        /// </summary>
        /// <param name="phoneNumber">手机号</param>
        /// <param name="excludeUserId">排除的用户ID</param>
        /// <returns>是否存在</returns>
        public async Task<bool> IsPhoneNumberExistsAsync(string phoneNumber, Guid? excludeUserId = null)
        {
            return await _userRepository.IsPhoneNumberExistsAsync(phoneNumber, excludeUserId);
        }

        #region 辅助方法

        /// <summary>
        /// 验证密码是否符合复杂度要求
        /// </summary>
        /// <param name="password">密码</param>
        /// <returns>是否有效</returns>
        private bool IsPasswordValid(string password)
        {
            if (string.IsNullOrWhiteSpace(password))
            {
                return false;
            }

            var options = _userRepository.Options;

            // 长度验证
            if (password.Length < options.RequiredLength)
            {
                return false;
            }

            // 唯一字符数量验证
            if (options.RequiredUniqueChars > 0)
            {
                if (password.Distinct().Count() < options.RequiredUniqueChars)
                {
                    return false;
                }
            }

            // 非字母数字验证
            if (options.RequireNonAlphanumeric && !password.Any(c => !char.IsLetterOrDigit(c)))
            {
                return false;
            }

            // 小写字母验证
            if (options.RequireLowercase && !password.Any(char.IsLower))
            {
                return false;
            }

            // 大写字母验证
            if (options.RequireUppercase && !password.Any(char.IsUpper))
            {
                return false;
            }

            // 数字验证
            if (options.RequireDigit && !password.Any(char.IsDigit))
            {
                return false;
            }

            return true;
        }

        #endregion
    }
}
